from simpy import Environment, Store

from x_pc.core import System
from x_pc.core.system_context import SysDataCtx
from x_pc.core.unit import Unit
from x_pc.model.model import TaskCtx, TaskStatus


class IQCCR(Unit):
    """
    210 出入货口设备组
    出入货口设备组(IQCCR)
    """
    store: Store = None

    def __init__(self, env: Environment, name: str, kwargs):
        Unit.__init__(self, env, name, kwargs)
        cache_nums = self.cache_nums()
        if not cache_nums or cache_nums < 1:
            cache_nums = 9999
        self.store = Store(env, cache_nums)

    def is_full(self):
        """
        缓存是否已满
        :return:
        """
        if not self.cache_nums():
            return False
        return len(self.store.items) == self.cache_nums()

    @staticmethod
    def device_type() -> int:
        return 210


class IQCCRSystem(System):
    # IQCCR列表
    iqccr_list: list[IQCCR] = []
    # 辅助idx
    idx = 0

    # 待AGV搬运的任务(集合)
    store_list: list[TaskCtx] = []

    sys_data: SysDataCtx = None

    def __init__(self, env: Environment, name: str, iqccr_list, sys_data: SysDataCtx):
        self.sys_data = sys_data
        super().__init__(env, name)
        self.__init_iqccr_list(iqccr_list)
        #
        self.iqccr_list = []
        self.store_list = []

    def __init_iqccr_list(self, iqccr_list):
        iqccr_list = [IQCCR(self.env, '出入货口设备组', iqccr) for iqccr in iqccr_list]
        #
        for iqccr in iqccr_list:
            if self.sys_data.is_valid_equ(iqccr):
                self.iqccr_list.append(iqccr)

    def run_task(self, task_ctx: TaskCtx):
        iqccr = None
        while self.running:
            if not self.iqccr_list:
                self.sys_data.logger.error(f'[PC] IQCCR 出入货口设备组 无可用口')
                break
            self.idx = (self.idx + 1) % len(self.iqccr_list)
            # 选择 栈板出入口
            iqccr = self.iqccr_list[self.idx]
            yield self.env.timeout(1)
            if not iqccr.is_full():
                break
        if not iqccr:
            task_ctx.task.set_run_status(TaskStatus.ERROR, self.sys_data)
            task_ctx.task.ext_last_info = f'IQCCR 出入货口设备组 无可用口'
            return
        task = task_ctx.task
        # 当为运动设备，修正上一条子指令
        if task.pre_process().ext_resource_type.is_movable():
            task.pre_process().end_pos = iqccr.loc()
        # 选择到了具体的 iqccr
        process = task_ctx.task.process
        process.begin_ts = self.env.now
        process.begin_pos = iqccr.loc()
        process.set_origin_pack_type(task.pre_process().target_pack_type)
        process.set_origin_sku_num(task.pre_process().target_sku_num)
        process.operate_pack_type = process.ext_work_type.operate_pack_type
        process.operate_pack_num = 1
        #
        process.device_type = iqccr.device_type()
        process.device_code = iqccr.device_code()
        iqccr.store.put(task_ctx)
        process.end_pos = iqccr.loc()
        process.end_ts = self.env.now
        self.store_list.append(TaskCtx(task, zbcr=iqccr))

    def __str__(self):
        return f'{self.__class__.__name__} ({self.iqccr_list})'
